package com.solo.system.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import com.solo.common.core.base.service.impl.BasicServiceImpl;
import com.solo.common.core.utils.NumberUtils;
import com.solo.common.core.utils.StringUtils;
import com.solo.common.core.utils.collection.CollUtils;
import com.solo.satoken.utils.LoginHelper;
import com.solo.system.api.entity.SysUser;
import com.solo.system.mapper.SysUserMapper;
import com.solo.system.mapper.SysUserPostMapper;
import com.solo.system.mapper.SysUserRoleMapper;
import com.solo.system.model.user.SysUserConvert;
import com.solo.system.model.user.req.ChangePasswordReq;
import com.solo.system.model.user.req.ResetPasswordReq;
import com.solo.system.model.user.req.UserCreateReq;
import com.solo.system.model.user.req.UserUpdateReq;
import com.solo.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Objects;

import static com.solo.common.core.utils.ServiceExceptionUtil.exception;
import static com.solo.system.api.consts.SystemCode.*;

/**
 * 用户Service实现类
 * @author 十一
 * @since 2023/09/04 17:27
 * 人生若只如初见，何事秋风悲画扇
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends BasicServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final SysUserMapper sysUserMapper;
    private final SysUserRoleMapper sysUserRoleMapper;
    private final SysUserPostMapper sysUserPostMapper;
    
    @Override
    public boolean create(UserCreateReq req) {
        SysUser entity = SysUserConvert.INSTANCE.convert(req);
        // 验证用户名是否唯一
        validateUsernameUnique(entity.getUsername(), null);
        // 验证电子邮件是否唯一
        validateEmailUnique(entity.getEmail(), null);
        // 验证手机号是否唯一
        validateMobileUnique(entity.getMobile(), null);
        // 密码加密
        entity.setPassword(BCrypt.hashpw(entity.getPassword()));
        // 保存用户
        return save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Collection<Long> userIds) {
        // 验证是否是当前登录用户，当前登录用户不能删除
        validateCurrentUser(userIds);
        // 删除用户角色关联
        sysUserRoleMapper.deleteByUserIds(userIds);
        // 删除用户岗位关联
        sysUserPostMapper.deleteByUserIds(userIds);
        // 删除用户
        return removeByIds(userIds);
    }

    @Override
    public boolean resetPassword(ResetPasswordReq req) {
        // 验证用户是否存在
        SysUser user = validateExists(req.getUserId());
        // 密码加密 TODO 密码是否加盐
        user.setPassword(BCrypt.hashpw(req.getPassword()));
        // 修改用户
        return updateById(user);
    }

    @Override
    public boolean changePassword(ChangePasswordReq req) {
        // 验证用户是否存在
        SysUser user = validateExists(LoginHelper.getUserId());
        // 验证密码是否正确
        validatePassword(req, user);
        // TODO 密码是否加盐
        user.setPassword(BCrypt.hashpw(req.getNewPassword()));
        // TODO 修改密码错误次数达到一定时，锁定账号
        return updateById(user);
    }

    @Override
    public boolean update(UserUpdateReq req) {
        SysUser entity = SysUserConvert.INSTANCE.convert(req);
        Long userId = entity.getUserId();
        // 验证用户是否存在
        validateExists(userId);
        // 验证用户名是否唯一
        validateUsernameUnique(entity.getUsername(), userId);
        // 验证电子邮件是否唯一
        validateEmailUnique(entity.getEmail(), userId);
        // 验证手机号是否唯一
        validateMobileUnique(entity.getMobile(), userId);
        return updateById(entity);
    }
    
    /**
     * 验证用户是否存在
     * @param userId 用户id
     * @return {@link SysUser }
     */
    SysUser validateExists(Long userId) {
        if (userId == null) {
            return null;
        }
        SysUser entity = mapper.selectOneById(userId);
        if (entity == null) {
            throw exception(USER_NOT_EXISTS);
        }
        return entity;
    }

    /**
     * 验证用户名唯一性
     * @param username 用户名
     * @param userId 用户id
     */
    void validateUsernameUnique(String username, Long userId) {
        if (StringUtils.isBlank(username)) {
            return;
        }
        SysUser user = sysUserMapper.selectByUsername(username);
        if (Objects.isNull(user)) {
            return;
        }
        // 如果前端传过来的 userId 是空或者和查出来的 userId 不一样，则说明用户名已存在
        if (!NumberUtils.equals(userId, user.getUserId())) {
            throw exception(USER_USERNAME_EXISTS, username);
        }
    }

    /**
     * 验证电子邮件唯一性
     * @param email 电子邮件
     * @param userId 用户id
     */
    void validateEmailUnique(String email, Long userId) {
        if (StringUtils.isBlank(email)) {
            return;
        }
        SysUser user = sysUserMapper.selectByEmail(email);
        if (Objects.isNull(user)) {
            return;
        }
        // 如果前端传过来的 userId 是空或者和查出来的 userId 不一样，则说明电子邮件已存在
        if (!NumberUtils.equals(userId, user.getUserId())) {
            throw exception(USER_EMAIL_EXISTS, email);
        }
    }

    /**
     * 验证手机号唯一性
     * @param mobile 手机号
     * @param userId 用户id
     */
    void validateMobileUnique(String mobile, Long userId) {
        if (StringUtils.isBlank(mobile)) {
            return;
        }
        SysUser user = sysUserMapper.selectByMobile(mobile);
        if (Objects.isNull(user)) {
            return;
        }
        // 如果前端传过来的 userId 是空或者和查出来的 userId 不一样，则说明手机号已存在
        if (!NumberUtils.equals(userId, user.getUserId())) {
            throw exception(USER_MOBILE_EXISTS, mobile);
        }
    }

    /**
     * 验证密码正确性
     * @param req 雷克
     * @param user 用户
     */
    void validatePassword(ChangePasswordReq req, SysUser user) {
        if (Objects.isNull(user)) {
            throw exception(USER_NOT_LOGIN);
        }
        if (!BCrypt.checkpw(req.getOldPassword(), user.getPassword())) {
            throw exception(OLD_PASSWORD_ERROR);
        }
        if (!StringUtils.equals(req.getNewPassword(), req.getConfirmPassword())) {
            throw exception(PASSWORD_NOT_EQUALS);
        }
        if (StringUtils.equals(req.getNewPassword(), req.getOldPassword())) {
            throw exception(NEW_PASSWORD_EQUALS_OLD);
        }
    }

    /**
     * 验证是否是当前用户
     * @param userIds 用户id
     */
    void validateCurrentUser(Collection<Long> userIds) {
        if (CollUtils.contains(userIds, LoginHelper.getUserId())) {
            throw exception(USER_CURRENT_NOT_DELETE);
        }
    }

}
